package com.lingjtx.auth.handle;

import com.alibaba.fastjson2.JSON;
import com.lingjtx.auth.dao.SysUserLoginLogMapper;
import com.lingjtx.auth.dao.UserMapper;
import com.lingjtx.auth.entity.SysUserLoginLog;
import com.lingjtx.common.core.constant.Const;
import com.lingjtx.common.core.constant.RedisConfig;
import com.lingjtx.common.core.constant.ResponseTip;
import com.lingjtx.common.core.exception.ResponseErrorException;
import com.lingjtx.common.core.handle.ObjectPool;
import com.lingjtx.common.core.token.AuthToken;
import com.lingjtx.common.core.token.LoginMode;
import com.lingjtx.common.core.token.UserDetail;
import com.lingjtx.common.core.token.UserVo;
import com.lingjtx.common.core.util.StringUtil;
import com.lingjtx.common.ip.IPUtils;
import com.lingjtx.common.redis.service.IRedisService;
import com.lingjtx.common.security.common.DataScopeType;
import com.lingjtx.common.security.model.LoginPo;
import com.lingjtx.common.thread.pooling.ObjectPoolTemplate;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.net.http.HttpClient;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Service
public class SystemAuthService implements AuthHandle {

    private final ObjectPoolTemplate<HttpClient> httpObjectPoolTemplate;
    private final IRedisService redisService;
    private final SysUserLoginLogMapper userLoginLogMapper;
    private final UserMapper userMapper;

    public SystemAuthService(@Qualifier("httpObjectPoolTemplate") ObjectPoolTemplate<HttpClient> httpObjectPoolTemplate,
                             IRedisService redisService, SysUserLoginLogMapper userLoginLogMapper, UserMapper userMapper) {
        this.httpObjectPoolTemplate = httpObjectPoolTemplate;
        this.redisService = redisService;
        this.userLoginLogMapper = userLoginLogMapper;
        this.userMapper = userMapper;
    }

    @Override
    public String getUserType() {
        return Const.UserType.SYSTEM;
    }

    @Override
    public UserVo selectUserByIdentifier(String identifier) {
        return userMapper.selectUserByIdentifier(identifier, getUserType());
    }

    @Override
    public void register(LoginMode model, LoginPo loginPo, UserVo user, HttpServletRequest request) {
        if (LoginMode.REFRESH_TOKEN.equals(model)) {
            // 加入权限相关更新
            String token = request.getHeader(Const.AuthTokenMap.AUTHORIZATION);
            UserDetail userDetail = AuthToken.getUser(token);
            if (Objects.nonNull(userDetail)) {
                setPerms(userDetail.getUserId(), loginPo);
            }
            return;
        }
        if (Objects.isNull(user)) {
            throw new ResponseErrorException(ResponseTip.RESPONSE_TIP_LOGIN_FAIL);
        } else {
            // 绑定权限相关操作
            setPerms(user.getUserId(), loginPo);

            // 插入一条登录日志
            insertLoginLog(request, user.getUserId(), loginPo);
        }
    }

    @Override
    public ObjectPool<HttpClient> getObjectPool() {
        return httpObjectPoolTemplate;
    }

    @Override
    public void insertLoginLog(HttpServletRequest request, Long userId, LoginPo loginPo) {
        String ip = request.getHeader("x-real-ip");
        if (userId == null) { // 退出登录
            String token = request.getHeader(Const.AuthTokenMap.AUTHORIZATION);
            UserDetail user = AuthToken.getUser(token);
            if (user != null) {
                SysUserLoginLog loginLog = userLoginLogMapper.selectLastLoginLog(user.getUserId());
                if (loginLog != null) {
                    loginLog.setLoginStatus(Const.LoginStatus.LOGOUT);
                    insertDatabase(ip, loginLog);
                }
            }
        } else { // 登录
            SysUserLoginLog loginLog = new SysUserLoginLog();
            loginLog.setUserId(userId);
            loginLog.setLoginStatus(Const.LoginStatus.LOGIN);
            loginLog.setDeviceModel(loginPo.getDeviceModel());
            loginLog.setDeviceUid(loginPo.getDeviceUid());
            loginLog.setOperationDevice(loginPo.getOperationDevice());
            loginLog.setCreateTime(new Date());
            redisService.set(RedisConfig.KEY_LOGIN_LOG + userId,
                    JSON.toJSONString(loginLog),
                    RedisConfig.TIMEOUT_REFRESH_TOKEN);
            insertDatabase(ip, loginLog);
        }
    }

    private void insertDatabase(String ip, SysUserLoginLog loginLog) {
        loginLog.setIp(ip);
        if (StringUtil.isNotEmpty(ip)) {
            loginLog.setAddress(IPUtils.getArea(ip).getName());
        }
        userLoginLogMapper.insert(loginLog);
    }

    private LoginPo setPerms(Long userId, LoginPo loginPo) {
        Byte scopeType = userMapper.selectUserMaxScopeTypeByUserId(userId);
        loginPo.setScopeType(scopeType);

        LoginPo entity = userLoginLogMapper.selectSysUserInfoByUserId(userId);
        if (Objects.nonNull(entity)) {
            loginPo.setCompanyId(entity.getCompanyId());
            loginPo.setAdminAccount(entity.getAdminAccount());

            List<String> perms = userMapper.selectPermsListByAdminAccountAndUserId(userId, entity.getAdminAccount(), entity.getCompanyId());
            loginPo.setPerms(perms);

            if (DataScopeType.CUSTOM.getCode().equals(scopeType)) { // 自定义数据权限
                List<Long> deptIds = userLoginLogMapper.selectAllChildIdsByDeptId(userId);
                loginPo.setScopeList(deptIds);
            }
        }
        return loginPo;
    }
}
